package com.njcb.ams.support.trade.filter;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.njcb.ams.pojo.enumvalue.TradeStatusCode;
import com.njcb.ams.support.codevalue.EnumCode;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;

import com.njcb.ams.repository.entity.SysTradeConsole;
import com.njcb.ams.factory.domain.AppContext;
import com.njcb.ams.store.stable.TradeConsoleService;
import com.njcb.ams.support.annotation.TradeFilter;
import com.njcb.ams.support.annotation.Trader;
import com.njcb.ams.support.annotation.enums.MonitorLevel;
import com.njcb.ams.support.exception.ExceptionUtil;
import com.njcb.ams.support.trade.TradeService;
import com.njcb.ams.support.trade.bean.TradeServiceBean;

/**
 * @author liuyanlong
 * 类功能描述：服务治理处理器
 */
@Service
@Lazy(false)
@TradeFilter(priority = 0)
public class ServiceGovernFilter implements TradeLayerFilter {
    private static final Logger logger = LoggerFactory.getLogger(ServiceGovernFilter.class);
    @Autowired
    private TradeConsoleService tradeConsoleService;

    public static ServiceGovernFilter getInstance() {
        return AppContext.getBean(ServiceGovernFilter.class);
    }

    @Override
    public Object doFilter(TradeFilterChain filterChain) throws Throwable {
        Trader anm = filterChain.getTraderAnnotation();
        ProceedingJoinPoint pjd = filterChain.getJoinPoint();
        if (MonitorLevel.LOG_MONITOR == anm.monitorLevel()) {
            return pjd.proceed();
        }
        SysTradeConsole sysServerConsole = tradeConsoleService.getConsole(anm);
        if (null == sysServerConsole || null == sysServerConsole.getTradeStatus()) {
            logger.error("交易控制信息为空:{},{}", anm.tradeCode(), anm.tradeName());
            sysServerConsole = new SysTradeConsole();
            sysServerConsole.setTradeStatus(TradeStatusCode.TRADE_STATUS_01.getCode());
            sysServerConsole.setTradeCode(anm.tradeCode());
            sysServerConsole.setTradeName(anm.tradeName());
        }
        if (logger.isDebugEnabled()) {
            logger.debug("交易控制信息:{}", sysServerConsole.toString());
            logger.debug("返回类型:{}", ((MethodSignature) pjd.getSignature()).getReturnType());
        }
        Object result = null;
        switch (EnumCode.valueOfCode(TradeStatusCode.class, sysServerConsole.getTradeStatus())) {
            case TRADE_STATUS_02:
                result = downTrade(pjd, anm, sysServerConsole);
                break;
            case TRADE_STATUS_03:
                result = fusingTrade(pjd, anm, sysServerConsole);
                break;
            case TRADE_STATUS_04:
                result = handleTrade(pjd, anm, sysServerConsole);
                break;
            default:
                // 流量与并发控制
                tradeConsoleService.tryAcquire(anm);
                try {
                    result = filterChain.doFilter(filterChain);
                } finally {
                    // 释放并发令牌
                    tradeConsoleService.releaseAcquire(anm);
                }
                break;
        }
        return result;
    }

    /**
     * 方法功能描述：测试挡板服务
     *
     * @param pjd
     * @param anm
     * @return
     */
    private Object handleTrade(ProceedingJoinPoint pjd, Trader anm, SysTradeConsole sysServerConsole) {
        logger.warn("交易[{}{}]执行挡板服务", anm.tradeCode(), anm.tradeName());
        TradeServiceBean serviceBean = TradeService.getTradeHandle(anm.tradeCode());
        try {
            return serviceBean.getMethod().invoke(AppContext.getBean(serviceBean.getBeanName()), pjd.getArgs());
        } catch (Exception e) {
            ExceptionUtil.printStackTrace(e);
            ExceptionUtil.throwAppException(e.getMessage());
        }
        return null;
    }

    /**
     * 方法功能描述：降级服务，默认成功
     *
     * @param pjd
     * @param anm
     * @return
     * @throws Exception
     */
    private Object downTrade(ProceedingJoinPoint pjd, Trader anm, SysTradeConsole sysServerConsole) throws Exception {
        logger.warn("交易[{}{}]执行降级服务", anm.tradeCode(), anm.tradeName());
        Object result = null;
        Class<?> returnType = ((MethodSignature) pjd.getSignature()).getReturnType();
        if (void.class.isAssignableFrom(returnType)) {
        } else if (returnType.isInterface()) {
            if (List.class.isAssignableFrom(returnType)) {
                result = new ArrayList<>();
            } else if (Map.class.isAssignableFrom(returnType)) {
                result = new HashMap<>();
            } else {
                ExceptionUtil.throwAppException("暂不支持[" + returnType + "]返回类型的交易定义");
            }
        } else {
            result = returnType.newInstance();
        }
        return result;
    }

    /**
     * 方法功能描述：熔断服务
     *
     * @param pjd
     * @param anm
     * @return
     * @throws Exception
     */
    private Object fusingTrade(ProceedingJoinPoint pjd, Trader anm, SysTradeConsole sysServerConsole) {
        logger.warn("交易[{}{}]执行熔断服务", anm.tradeCode(), anm.tradeName());
        ExceptionUtil.throwAppException(sysServerConsole.getTradeMsg());
        return null;
    }

}
